
import caller
import webelement
import time
import json

class Cookie:
    def __init__(self, cookie = {}):
        self.cookie = cookie

    def isNull(self):
        if self.name() == None and self.value() == None:
            return True
        return False

    def setDomain(self, value):
        self.cookie['domain'] = value
    
    def domain(self):
        try:
            return self.cookie['domain']
        except:
            return None

    def setHttponly(self, value):
        self.cookie['httponly'] = value

    def isHttponly(self):
        try:
            return self.cookie['httponly']
        except:
            return None

    def setName(self, value):
        self.cookie['name'] = value

    def name(self):
        try:
            return self.cookie['name']
        except:
            return None

    def setValue(self, value):
        self.cookie['value'] = value

    def value(self):
        try:
            return self.cookie['value']
        except:
            return None

    def setPath(self, value):
        self.cookie['path'] = value

    def path(self):
        try:
            return self.cookie['path']
        except:
            return None

    def setSecure(self, value):
        self.cookie['secure'] = value

    def secure(self):
        try:
            return self.cookie['secure']
        except:
            return None

    def setExpiry(self, value):
        self.cookie['expiry'] = value

    def expiry(self):
        try :
            return self.cookie['expiry']
        except:
            return None
        
    def expires(sefl):
        try :
            return self.cookie['expires']
        except:
            return None

    def toJson(self):
        return json.dumps(self.cookie)

class CookieJar:
    def __init__(self, cookies = []):
        self.cookies = cookies

    def getByName(self, name):
        for c in self.cookies:
            if c.name() == name:
                return c
        return None

    def getByIndex(self, index):
        count = index
        for c in self.cookies:
            if count == 0:
                return c
            count -= 1
        return None

    def set(self, name, value):
        hasOne = False
        for c in self.cookies:
            if c.name() == name:
                c.setValue(value)
                hasOne = True
        if not hasOne:
            c = Cookie()
            c.setName(name)
            c.setValue(value)
            self.cookies.append(c)

    def setco(self, cookie):
        hasOne = False
        for c in self.cookies:
            if c.name() == cookie.name():
                self.cookies.remove(c)
                self.cookies.append(cookie)
                hasOne = True
        if not hasOne:
            self.cookies.append(cookie)

    def loadFromJson(self, jsonstr):
        cookie_contents = json.loads(jsonstr)
        for c in cookie_contents:
            self.cookies.append(Cookie(c))
            
    def toJson(self):
        cookie_contents = []
        for c in self.cookies:
            cookie_contents.append(c.cookie)

        return json.dumps(cookie_contents);

    def size(self):
        return self.cookies.count()
    
class WebPage:
    def __init__(self, pageref, cr, rules = []):
        self.ref = pageref
        self.cr = cr
        self.rules = rules
        
    def isFailed(self):
        return self.cr.isFailed()

    def loadUrl(self, address, operation, sync, timeout = 0, dtimeout = -1, headers = [], bodyString = "", encoding = ""):
        syncstr = "0"
        if sync == True:
            syncstr = "1"
        headerstring = json.dumps(headers)
        args = []
        if dtimeout == -1:
            args = [self.ref, syncstr, address, operation, headerstring, bodyString, encoding, str(timeout)]
        else:
            args = [self.ref, syncstr, address, operation, headerstring, bodyString, encoding, str(timeout), str(dtimeout)]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_LOADURL_LONG_REF_STRING_ADDRESS_STRING_OPERATION_QMAP_STRING_STRING_HEADERS_STRING_BODYSTRING_STRING_ENCODING, args)
        retobj = self.cr.getReturnObjValue(ret)
        if retobj == None:
            return -1
        else:
            return retobj['error']

    def setHtml(self, html, url):
        args = [self.ref, html, url]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_SETHTML_LONG_REF_STRING_HTML, args)

    def setSetting(self, name, setting):
        args = [self.ref, name, setting]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_SETSETTING_LONG_REF_STRING_NAME_STRING_SETTING, args)

    def getTitle(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_GETTITLE_LONG_REF, args)
        return self.cr.getReturnValue(ret)

    def renderTreeDump(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_RENDERTREEDUMP_LONG_REF, args)
        return self.cr.getReturnValue(ret)

    def getDOMTreeSource(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_GETDOMTREESOURCE_LONG_REF, args)
        return self.cr.getReturnValue(ret)

    def getPageSource(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_GETPAGESOURCE_LONG_REF, args)
        return self.cr.getReturnValue(ret)

    def getUrl(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_GETURL_LONG_REF, args)
        return self.cr.getReturnValue(ret)

    def goBack(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_GOBACK_LONG_REF, args)
        return self.cr.getReturnNumValue(ret)

    def goForward(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_GOFORWARD_LONG_REF, args)
        return self.cr.getReturnNumValue(ret)

    def refresh(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_REFRESH_LONG_REF, args)
        return self.cr.getReturnNumValue(ret)

    def getElementById(self, query):
        args = [self.ref, query]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, args)
        return self.cr.getReturnValue(ret)

    def getElementsByTagName(self, query):
        args = [self.ref, query]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_GETELEMENTBYID_LONG_REF_STRING_QUERY, args)
        array = []
        if not self.cr.getReturnObjValue(ret) == None:
            array = self.cr.getReturnObjValue(ret)['array']
        elements = []
        for ref in array:
            elements.append(webelement.WebElement(ref, self.ref, self.cr))
        return elements;

    def getElementsByName(self, query):
        args = [self.ref, query]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_GETELEMENTSBYNAME_LONG_REF_STRING_QUERY, args)
        array = []
        if not self.cr.getReturnObjValue(ret) == None:
            array = self.cr.getReturnObjValue(ret)['array']
        elements = []
        for ref in array:
            elements.append(webelement.WebElement(ref, self.ref, self.cr))
        return elements

    def getElementByCssSelector(self, query):
        args = [self.ref, query]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_GETELEMENTBYCSSSELECTOR_LONG_REF_STRING_QUERY, args)
        ref = self.cr.getReturnValue(ret)
        return webelement.WebElement(ref, self.ref, self.cr)

    def getElementsByCssSelector(self, query):
        args = [self.ref, query]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_GETELEMENTSBYCSSSELECTOR_LONG_REF_STRING_QUERY, args)
        array = []
        if not self.cr.getReturnObjValue(ret) == None:
            array = self.cr.getReturnObjValue(ret)['array']
        elements = []
        for ref in array:
            elements.append(webelement.WebElement(ref, self.ref, self.cr))
        return elements

    def activeElement(self):
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_ACTIVEELEMENT, args)
        ref = self.cr.getReturnValue(ret);
        return webelement.WebElement(long(ref), self.ref, self.cr)

    def setViewportSize(self, w, h):
        args = [self.ref, w, h]
        self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_SETVIEWPORTSIZE_INT_W_INT_H, args)

    # return link , headers : {["name": xxx, "value": xxx], [...]}
    def download(self, element, timeout):
        args = [element.ref, timeout]
        ret = self.cr.call(element.pageref, caller.Function.WEBPAGE_LONG_DOWNLOAD_LONG_REF, args)
        dinfo = self.cr.getReturnDownloadInfoValue(ret)
        return dinfo["link"], dinfo["headers"]

    def click(self, element, targetBlank = 0, timeout = 0, dtimeout = 0):
        if not element.pageref == self.ref:
            return {'error':-1, 'page':None}
        args = [element.ref, 1, targetBlank, timeout]
        if targetBlank:
            args.append(dtimeout);

        ret = self.cr.call(self.ref, caller.Function.WEBELEMENT_LONG_CLICK_LONG_REF, args)
        ref = self.cr.getReturnObjValue(ret);
        if ref == None:
            return {'error':-1, 'page':None}
        page = None
        if ref['error'] >= 0:
            page = WebPage(ref['page'], self.cr)

        return {'error':ref['error'], 'page':page}

    def mouseMove(self, element):
        if not element.pageref == self.ref:
            return
        args = [element.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_MOUSEMOVE_LONG_REF, args)

    def mouseMovePos(self, x, y):
        args = [x, y]
        ret = self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_MOUSEMOVE_INT_X_INT_Y, args)

    def sendKeys(self, element, typestring, keys, openNewPage = 0, timeout = 0, dtimeout = 0):
        if not element.pageref == self.ref:
            return {'error':-1, 'page':None}
        args = [element.ref, typestring, keys, 1, openNewPage, timeout]
        if openNewPage:
            args.append(dtimeout)

        ret = self.cr.call(self.ref, caller.Function.WEBELEMENT_LONG_SENDKEYS_LONG_REF_STRING_TYPE_LONG_KEYS, args)
        ref = self.cr.getReturnObjValue(ret);
        if ref == None:
            return {'error':-1, 'page':None}
        page = None
        if ref['error'] >= 0:
            page = WebPage(ref['page'], self.cr)

        return {'error':ref['error'], 'page':page}

    def setCookies(self, cookies):
        args = [self.ref]
        cookiesjson = json.dumps(cookies)
        args.append(cookiesjson)
        ret = self.cr.call(self.ref, caller.Function.WEBKIT_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, args)
        return self.cr.getReturnNumValue(ret)
    
    def setCookieJar(self, jar):
        args = [self.ref]
        cookiesjson = jar.toJson()
        args.append(cookiesjson)
        ret = self.cr.call(self.ref, caller.Function.WEBKIT_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, args)
        return self.cr.getReturnNumValue(ret)
 
    
    def getCookies(self):
        cookies = []
        args = [self.ref]
        ret = self.cr.call(self.ref, caller.Function.WEBKIT_STRING_COOKIES_LONG_REF, args)
        cookiesobj = self.cr.getReturnObjValue(ret)
        if ret == None:
            return []
        for c in cookiesobj:
            cookies.append(Cookie(c))
        return cookies

    def getCookieJar(self):
        return CookieJar(self.getCookies())

    def deleteCookie(self, name):
        args = [self.ref, name]
        ret = self.cr.call(self.ref, caller.Function.WEBKIT_LONG_DELETECOOKIE_LONG_REF_STRING_CNAME, args)
        return self.cr.getReturnNumValue(ret)

    def destroy(self, needCloseSocket = False):
        args = [self.ref]
        self.cr.call(self.ref, caller.Function.WEBKIT_LONG_DESTROY_LONG_REF, args)
        if needCloseSocket:
            self.cr.close()

    def setDestroyTime(self, timeMS):
        args = [self.ref, timeMS]
        self.cr.call(self.ref, caller.Function.WEBPAGE_LONG_SET_DESTROY_TIME, args)
        
    def webPageImageBuffer(self):
        result = self.cr.call(self.ref, caller.Function.WEBPAGE_STRING_RENDER_IMAGE_BASE64, [])
        buf = self.cr.getReturnValue(result)
        return buf

    def setFilterRule(self, rules):
        self.rules = rules
        jsonstr = json.dumps(self.rules)
        self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_SETFILTERRULE_STRING_RULES, [jsonstr])

    def scroll(self, x, y):
        args = [x, y]
        self.cr.call(self.ref, caller.Function.WEBPAGE_VOID_SCROLL, args)

    def waitForCssSelector(self, query, times):
        if self.isFailed():
            return False
        count = times
        while count:
            if len(self.getElementsByCssSelector(query)) <= 0 :
                time.sleep(0.2)
                count -= 1
            else:
                return True
        return False

